// JsonFromNodeXlsxTools.ts
// write by Ethan @2021.12.18
// edit @2022.5.31

export function jsonObjectTree(data: any[][], r = 0, l = 0) {
    let output = {};
    makeObj(0, 0, output, data);
    return output;
}

export function jsonArrayTree(data: any[][], r = 0, l = 0) {
    let output = [];
    makeArray(0, 0, output, data);
    return output;
}

function isDirectArrayKey(value) {
    if (typeof (value) == 'string') {
        let v = value.trim();
        if (v.startsWith('[') && v.endsWith(']')) {
            return true;
        }
    }
    return false;
}

function isArrayKey(value) {
    if (typeof (value) == 'string') {
        if (value.endsWith('-')) return true;
    }
    return false;
}

function isObjectKey(value) {
    if (typeof (value) == 'string') {
        if (value.endsWith('.')) return true;
    }
    return false;
}

function isTime(key) {
    if (typeof (key) == 'string') {
        if (key.endsWith('<Time>')) return true;
    }
    return false;
}

function isDate(key) {
    if (typeof (key) == 'string') {
        if (key.endsWith('<Date>')) return true;
    }
    return false;
}

function isKeyValue(key) {
    if (typeof (key) == 'string') {
        if (key.endsWith('<k,v>')) return true;
    }
}

// 要确保输入的key是需要leankey操作的再使用该函数
function leanKey(key: string) {
    if (key.endsWith('<Date>')) return key.substring(0, key.length - 6);
    if (key.endsWith('<Time>')) return key.substring(0, key.length - 6);
    else if (key.endsWith('<k,v>')) return key.substring(0, key.length - 5);
    return key.substring(0, key.length - 1);
}

function parseTime(raw: number): Date {
    let oneDay = 86400000;
    let msOfTheDay = raw * oneDay;
    let date = new Date(msOfTheDay);
    return date;
}

function parseDate(raw: number): Date {
    if (typeof (raw) == 'string') {
        return new Date(raw);
    }
    let oneDay = 86400000;
    if (raw >= 1) { // 表示完整日期
        let day = new Date(1900, 0, Math.floor(raw - 1), 0, 0, 0, Math.floor(raw % 1 * oneDay));
        return day;
    } else {
        return parseTime(raw);
    }
}

function parseKeyValue(raw: string): { key: string, value: string | number } {
    let [key, value] = raw.split(',');
    return { key, value: (value != null ? Number(value) : value) };
}

function parseDirectArray(raw: string): any[] {
    if (isDirectArrayKey(raw)) {
        let trimed = raw.trim();
        let content = trimed.substring(1, trimed.length - 1);
        let item = content.split(',');
        let result: any[] = item.map(_ => {
            if (isNaN(Number(_))) {
                return _;
            }
            return Number(_);
        });
        return result;
    }
}

function makeObj(r: number, l: number, obj: {}, data: any[][]) {
    for (let pr = r; pr < data.length; pr++) {
        let row = data[pr];
        // console.log('jfn', r, pr, row);

        // 判断已经结束了，递归末端
        let end = false;
        if (pr > r) {
            for (let _l = l - 1; _l >= 0; _l--) {
                let _v = row[_l];
                if (pr == r && _l == l - 1) continue;
                if (_v != null) end = true;
            }
        }
        if (end) break;

        // 内层递归用到的行，在本层是空行，略过
        let value = row[l];
        if (value == null) continue;
        let value2 = row[l + 1];

        if (isObjectKey(value)) {
            value = leanKey(value);
            obj[value] ?? (obj[value] = {});
            makeObj(pr, l + 1, obj[value], data);
        } else if (isArrayKey(value)) {
            value = leanKey(value);
            obj[value] ?? (obj[value] = []);
            makeArray(pr, l + 1, obj[value], data);
        } else if (isDirectArrayKey(value2)) {
            obj[value] = parseDirectArray(value2);
        } else if (isDate(value)) {
            value = leanKey(value);
            let vov = row[l + 1];
            let date = parseDate(vov);
            obj[value] = date;
        } else if (isTime(value)) {
            value = leanKey(value);
            let vov = row[l + 1];
            let date = parseTime(vov);
            obj[value] = date;
        } else if (isKeyValue(value)) {
            value = leanKey(value);
            let vov = row[l + 1];
            let kvObj = parseKeyValue(vov);
            obj[value] = kvObj;
        } else {
            let vov = row[l + 1];
            obj[value] = vov;
        }
    }
};

function makeArray(r: number, l: number, obj: any[], data: any[][]) {
    for (let pr = r; pr < data.length; pr++) {
        let row = data[pr];

        // 判断已经结束了，递归末端
        let end = false;
        if (pr > r) {
            for (let _l = l - 1; _l >= 0; _l--) {
                let _v = row[_l];
                if (pr == r && _l == l - 1) continue;
                if (_v != null) end = true;
            }
        }
        if (end) break;

        // 内层递归用到的行，在本层是空行，略过
        let value = row[l];
        if (value == null) continue;
        let value2 = row[l + 1];

        if (isObjectKey(value)) {
            let _obj = {};
            obj.push(_obj);
            makeObj(pr, l + 1, _obj, data);
        } else if (isArrayKey(value)) {
            let array = [];
            obj.push(array);
            makeArray(pr, l + 1, array, data);
        } else if (isDirectArrayKey(value2)) {
            obj[value] = parseDirectArray(value2);
        } else {
            obj.push(value)
        }
    }
}